import { _decorator, Component, Node, Vec3, Color, Graphics } from 'cc';

const { ccclass, property } = _decorator;

export class GridNode {
    public x: number;
    public y: number;
    public walkable: boolean = true;
    public gCost: number = 0;
    public hCost: number = 0;
    public parent: GridNode | null = null;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}

/**
 * 寻路网格系统
 * 
 * 功能：
 * 1. 管理寻路网格数据
 * 2. 处理网格节点状态
 * 3. 提供网格查询接口
 * 4. 支持动态更新
 * 
 * 特点：
 * 1. 高效的网格存储
 * 2. 动态障碍物更新
 * 3. 网格状态缓存
 * 4. 支持不同地形代价
 */
@ccclass('Grid')
export class Grid extends Component {
    @property
    public nodeSize: number = 1;

    @property
    public gridWorldSize: Vec3 = new Vec3(100, 1, 100);

    @property(Graphics)
    private debugGraphics: Graphics | null = null;

    private nodes: GridNode[][] = [];
    private gridSizeX: number = 0;
    private gridSizeY: number = 0;

    start() {
        this.initGrid();
    }

    private initGrid() {
        this.gridSizeX = Math.round(this.gridWorldSize.x / this.nodeSize);
        this.gridSizeY = Math.round(this.gridWorldSize.z / this.nodeSize);

        // 创建网格节点
        for (let x = 0; x < this.gridSizeX; x++) {
            this.nodes[x] = [];
            for (let y = 0; y < this.gridSizeY; y++) {
                this.nodes[x][y] = new GridNode(x, y);
            }
        }

        // 更新节点可行走状态
        this.updateWalkableNodes();
    }

    private updateWalkableNodes() {
        // TODO: 检查物理碰撞来确定节点是否可行走
    }

    public getNodeFromWorldPoint(worldPosition: Vec3): GridNode | null {
        const percentX = (worldPosition.x + this.gridWorldSize.x / 2) / this.gridWorldSize.x;
        const percentY = (worldPosition.z + this.gridWorldSize.z / 2) / this.gridWorldSize.z;

        const x = Math.floor(percentX * this.gridSizeX);
        const y = Math.floor(percentY * this.gridSizeY);

        if (x >= 0 && x < this.gridSizeX && y >= 0 && y < this.gridSizeY) {
            return this.nodes[x][y];
        }
        return null;
    }

    public getWorldPosition(node: GridNode): Vec3 {
        const x = (node.x * this.nodeSize + this.nodeSize / 2) - this.gridWorldSize.x / 2;
        const z = (node.y * this.nodeSize + this.nodeSize / 2) - this.gridWorldSize.z / 2;
        return new Vec3(x, 0, z);
    }

    public getNeighbors(node: GridNode): GridNode[] {
        const neighbors: GridNode[] = [];
        
        for (let x = -1; x <= 1; x++) {
            for (let y = -1; y <= 1; y++) {
                if (x === 0 && y === 0) continue;

                const checkX = node.x + x;
                const checkY = node.y + y;

                if (checkX >= 0 && checkX < this.gridSizeX &&
                    checkY >= 0 && checkY < this.gridSizeY) {
                    neighbors.push(this.nodes[checkX][checkY]);
                }
            }
        }

        return neighbors;
    }

    public updateNode(worldPosition: Vec3, walkable: boolean) {
        const node = this.getNodeFromWorldPoint(worldPosition);
        if (node) {
            node.walkable = walkable;
        }
    }

    // Debug 绘制
    public drawDebugGrid() {
        if (!this.debugGraphics) return;

        this.debugGraphics.clear();

        for (let x = 0; x < this.gridSizeX; x++) {
            for (let y = 0; y < this.gridSizeY; y++) {
                const node = this.nodes[x][y];
                const worldPos = this.getWorldPosition(node);

                this.debugGraphics.lineWidth = 1;
                this.debugGraphics.strokeColor = node.walkable ? Color.GREEN : Color.RED;
                this.debugGraphics.rect(
                    worldPos.x - this.nodeSize / 2,
                    worldPos.z - this.nodeSize / 2,
                    this.nodeSize,
                    this.nodeSize
                );
                this.debugGraphics.stroke();
            }
        }
    }
} 